package typejump.engine;

import java.awt.image.BufferedImage;

/**
 * Represents a sequence of frames in an animation, including a duration
 * for animation length, and a GameAction which may trigger when the
 * animation ends.
 * @author g
 *
 */
public class Animation {
	public Animation(BufferedImage[] frames, double duration, boolean bounce, GameAction endTrigger) {
		this.frames = frames;
		this.duration = duration;
		this.bounce = bounce;
	}
	
	public Animation(BufferedImage[] frames, double duration, boolean bounce) {
		this(frames, duration, false, null);
	}

	public Animation(BufferedImage[] frames, double duration) {
		this(frames, duration, false);
	}
	
	private GameAction endTrigger;
	private BufferedImage[] frames = null;
	private double duration = 1;
	/** Normally when looping, the animation will start over from the beginning.
	 * If this flag is set, the animation will start going backwards when
	 * it reaches the end, then go forwards again, like it's "bouncing".
	 */
	private boolean bounce = false;
	
	/**
	 * Returns the GameAction which should execute when this animation ends
	 * @return
	 */
	public GameAction getEndTrigger() {
		return endTrigger;
	}
	
	/**
	 * Sets the GameAction which should execute when this animation ends.
	 * Note that this may be overriden by the Sprite class excuting this
	 * Animation.
	 * @param g
	 */
	public void setDefaultEndTrigger(GameAction g) {
		this.endTrigger = g;
	}
	
	/**
	 * Returns the frame that this animation should be at given the
	 * time in since the animation began. If the time is greater
	 * than the duration, the animation will loop appropriately.
	 * @param time - The time in second since the animation began
	 * @return
	 */
	public int getFrame(double time) {
		if (frames == null || frames.length == 0 || duration <= 0)
			return -1;

		int progress = (int)( frames.length  *  (time / duration) );
		
		boolean forward = !bounce || (progress / frames.length) % 2 == 0;
		progress %= frames.length;
		
		if (forward) {
			return progress;
		} else {
			return frames.length-1-progress;
		}
	}
	
	/**
	 * Returns the BufferedImage containing the image data
	 * of this Animation at the frame which should be
	 * active at the given time.
	 * @param time - seconds since the animation started playing
	 * @return
	 */
	public BufferedImage getImage(double time) {
		return frames[getFrame(time)];
	}
	
	/**
	 * Returns the number of frames in the Animation
	 * @return
	 */
	public int frameCount() {
		return frames.length;
	}
	
	/**
	 * Returns the time (in seconds) it takes
	 * to get through all the frames in this Animation
	 * @return
	 */
	public double getDuration() {
		return duration;
	}
	
	/**
	 * Returns the width of the frame at the given time
	 * @param time - seconds since the Animation started playing
	 * @return
	 */
	public int getWidth(double time) {
		int frame = getFrame(time);
		if (frame >= 0) {
			return frames[frame].getWidth();
		}
		return -1;
	}
	
	/**
	 * Returns the height of the frame at the given time
	 * @param time - seconds since the Animation started playing
	 * @return
	 */
	public int getHeight(double time) {
		int frame = getFrame(time);
		if (frame >= 0) {
			return frames[frame].getHeight();
		}
		return -1;
	}
}
